package com.zkyc.framework.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class DownloadFileUtil {
    /**
     * 2      * TODO 下载文件到本地
     * 3      * @author Libingchuan
     * 4      * @date Sep 11, 2021 11:45:31 AM
     * 5      * @param fileUrl 文件下载地址
     * 6      * @param filePath 本地存放路径
     * 6      * @param fileType 文件类型：doc/pdf
     * 7      * @throws Exception
     * 8
     */
    public static File download(String fileUrl, String filePath, String fileName, String fileType) throws Exception {
        /**
         * 封装一个下载附件的方法
         *
         */
        String savePath = "";
        File file = null;
        if (StringUtils.isNotBlank(fileUrl)) {
            savePath = writeFileHttpsUrl(fileUrl, filePath, fileName, fileType);
            log.info("-----------savePath: " + savePath);
            /**
             * 下载附件后判断文件是否有效
             */
            file = new File(savePath);
            if (file.exists() && file.isFile()) {
                log.info("----------附件大小-----------" + file.length());
                if (file.length() > (5 * 1024)) {
                    if (StringUtils.isNotBlank(savePath)) {
                        log.info("-----------文件临时保存在: " + savePath);
                    }
                } else {
                    log.info("无效文件 删除");
                    file.delete();
                }
            }
        }
        return file;
    }

    /**
     * 下载文件返回物理存储路径
     *
     * @param fileUrl
     * @param filePath
     * @param fileName
     * @param fileType
     * @return
     * @throws Exception
     */
    public Map<String, Object> downloadFile(String fileUrl, String filePath, String fileName, String fileType) throws Exception {
        /**
         * 封装一个下载附件的方法
         *
         */
        String savePath = "";
        File file = null;
        if (StringUtils.isNotBlank(fileUrl)) {
            savePath = writeFileHttpsUrl(fileUrl, filePath, fileName, fileType);
            log.info("-----------savePath: " + savePath);
            /**
             * 下载附件后判断文件是否有效
             */
            file = new File(savePath);
            if (file.exists() && file.isFile()) {
                log.info("----------附件大小-----------" + file.length());
                if (file.length() > (5 * 1024)) {
                    if (StringUtils.isNotBlank(savePath)) {
                        log.info("-----------文件临时保存在: " + savePath);
                    }
                } else {
                    log.info("无效文件 删除");
                    file.delete();
                }
            }
        }
        Map<String, Object> fileMap = new HashMap<>();
        fileMap.put("file", file);
        fileMap.put("filePath", savePath);
        fileMap.put("size", (file.length() / 1024) + "KB");
        return fileMap;
    }


    /**
     * 从网络Url中下载文件
     *
     * @param fileUrl
     * @param filePath
     * @param fileType
     * @return
     */
    public static String writeFileHttpsUrl(String fileUrl, String filePath, String fileName, String fileType) {

        log.info("--------------下载附件开始，请稍后：" + fileUrl);
        // 文件保存位置
        String date = "";
        String file = "";
        try {
            date = getDateStrFormat3(new Date());
            filePath = filePath + date;
            File fileDir = new File(filePath);
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            //通过url地址获取文件的后缀名称
            URL uri = new URL(fileUrl);
            String fileExtension = getFileExtension(uri);
            if (StringUtils.isNotEmpty(fileType)) {
                //通过时间戳给文件重命名
                fileName = fileName + "." + fileType;
            } else if(StringUtils.isNotEmpty(fileExtension)){
                //如果没有通过url地址获取到文件后缀则通过fileType来匹配
                fileName = fileName + "." + fileExtension;
            }
//        file = filePath+ File.separator +fileName; //File.separator是反斜杠
            file = filePath + "/" + fileName;
            log.info("--------------创建并返回文件路径：" + file);
            doPostContentDownload(fileUrl, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 从url文件下载地址中获取文件后缀名称
     *
     * @ extUrl
     */
    public static String getFileExtension(URL extUrl) {
        //URL: "https://www.ecutdl.cn/IAP//resources/0510.pdf"
        // String filename = "";
        //PATH: /IAP//resources/0510.pdf
        String extension = "";
        String path = extUrl.getPath();
        String[] pathContents = path.split("[\\\\/]");
        if (pathContents != null) {
            int pathContentsLength = pathContents.length;
            //System.out.println("Path Contents Length: " + pathContentsLength);
//            for (int i = 0; i < pathContents.length; i++) {
//                System.out.println("Path " + i + ": " + pathContents[i]);
//            }
            //lastPart:0510.pdf
            String lastPart = pathContents[pathContentsLength - 1];
            String[] lastPartContents = lastPart.split("\\.");
            if (lastPartContents != null && lastPartContents.length > 1) {
                int lastPartContentLength = lastPartContents.length;
                // System.out.println("Last Part Length: " + lastPartContentLength);
                String name = "";
                for (int i = 0; i < lastPartContentLength; i++) {
                    // System.out.println("Last Part " + i + ": "+ lastPartContents[i]);
                    if (i < (lastPartContents.length - 1)) {
                        name += lastPartContents[i];
                        if (i < (lastPartContentLength - 2)) {
                            name += ".";
                        }
                    }
                }
                extension = lastPartContents[lastPartContentLength - 1];
                // filename = name + "." +extension;
                // System.out.println("Name: " + name);
                // System.out.println("Extension: " + extension);
                // System.out.println("Filename: " + filename);
            }
        }
        return extension;
    }


    private static void trustAllHttpsCertificates() throws Exception {

        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    static class miTM implements TrustManager, X509TrustManager {
        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }


        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }

        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }
    }


    public static void doPostContentDownload(String fileUrl, String filePath) {

        log.info("--------------访问HTTPS资源开始--------------url:\n" + fileUrl);
        InputStream in = null;
        FileOutputStream fos = null;
        HttpURLConnection conn = null;
        try {
            // 该部分必须在获取connection前调用
            trustAllHttpsCertificates();

            HostnameVerifier hv = new HostnameVerifier() {
                @Override
                public boolean verify(String urlHostName, SSLSession session) {
                    log.info("-----------Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            conn = (HttpURLConnection) new URL(fileUrl).openConnection();

            in = conn.getInputStream();
            File file = new File(filePath);
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[4096];
            int len = -1;
            while ((len = in.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
//			log.info("---------文件写入成功----------fos： " + fos.toString());
        } catch (Exception e) {
//            log.info("----------下载地址异常---------");
            e.printStackTrace();
            // log.error("发送 GET 请求出现异常！\t请求ID:\n"+e.getMessage()+"\n");
        } finally {// 使用finally块来关闭输出流、输入流
            try {
                if (fos != null) {
                    fos.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                log.error("关闭数据流出错了！\n" + ex.getMessage() + "\n");
            }
        }
    }


    /**
     * 功能描述 :MultipartFile转file对象
     *
     * @param
     * @return
     * @author uncle
     * @date 2019/5/10 18:30
     */
    public static File MultipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 用当前时间作为文件名，防止生成的临时文件重复
        try {
            File file = File.createTempFile(System.currentTimeMillis() + "", prefix);

            multiFile.transferTo(file);

            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 将文件名解析成文件的上传路径
     */
    public static File saveMultipartFile(MultipartFile file, String savePath, String fileName) {
        String date = DownloadFileUtil.getDateStrFormat3(new Date());
        String suffix = getExtensionName(file.getOriginalFilename());
        try {
            fileName = fileName + "." + suffix;
            String filePath = savePath + date + "/" + fileName;
            File fileDir = new File(savePath);
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            // getCanonicalFile 可解析正确各种路径
            File dest = new File(filePath).getCanonicalFile();
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                if (!dest.getParentFile().mkdirs()) {
                    System.out.println("was not successful.");
                }
            }
            // 文件写入
            file.transferTo(dest);
            return dest;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static String getDateStrFormat3(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String strDate = sdf.format(date);
        return strDate;
    }

    /**
     * 获取文件扩展名，不带 .
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }


    public static Double checkFileSize(Long len, String unit) {
//        long len = file.length();
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        return fileSize;
    }
}